home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-1.iso / math / ast51src.zip / ASTROLOG.C < prev    next >
C/C++ Source or Header  |  1995-12-31  |  47KB  |  1,772 lines

  1. /*
  2. ** Astrolog (Version 5.10) File: astrolog.c
  3. **
  4. ** IMPORTANT NOTICE: The graphics database and chart display routines
  5. ** used in this program are Copyright (C) 1991-1995 by Walter D. Pullen
  6. ** (Astara@msn.com). Permission is granted to freely use and
  7. ** distribute these routines provided one doesn't sell, restrict, or
  8. ** profit from them in any way. Modification is allowed provided these
  9. ** notices remain with any altered or edited versions of the program.
  10. **
  11. ** The main planetary calculation routines used in this program have
  12. ** been Copyrighted and the core of this program is basically a
  13. ** conversion to C of the routines created by James Neely as listed in
  14. ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
  15. ** available from Matrix Software. The copyright gives us permission to
  16. ** use the routines for personal use but not to sell them or profit from
  17. ** them in any way.
  18. **
  19. ** The PostScript code within the core graphics routines are programmed
  20. ** and Copyright (C) 1992-1993 by Brian D. Willoughby
  21. ** (brianw@sounds.wa.com). Conditions are identical to those above.
  22. **
  23. ** The extended accurate ephemeris databases and formulas are from the
  24. ** calculation routines in the program "Placalc" and are programmed and
  25. ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
  26. ** (alois@azur.ch). The use of that source code is subject to
  27. ** regulations made by Astrodienst Zurich, and the code is not in the
  28. ** public domain. This copyright notice must not be changed or removed
  29. ** by any user of this program.
  30. **
  31. ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
  32. ** X Window graphics initially programmed 10/23-29/1991.
  33. ** PostScript graphics initially programmed 11/29-30/1992.
  34. ** Last code change made 12/27/1995.
  35. */
  36.  
  37. #include "astrolog.h"
  38.  
  39.  
  40. /*
  41. ******************************************************************************
  42. ** Program Dispatch Procedures.
  43. ******************************************************************************
  44. */
  45.  
  46. /* Initialize the Ansi color arrays with the color to print each object in. */
  47.  
  48. void InitColors()
  49. {
  50.   int i;
  51.  
  52.   kObjA[0] = kElemA[eEar];
  53.   for (i = 1; i <= 10; i++)
  54.     kObjA[i] = kSignA(ruler1[i]);
  55.   for (i = 11; i <= 15; i++)
  56.     kObjA[i] = kMainA[8];
  57.   for (i = 16; i <= 20; i++)
  58.     kObjA[i] = kMainA[6];
  59.   for (i = 1; i <= cSign; i++)
  60.     kObjA[cuspLo+i-1] = kSignA(i);
  61.   for (i = uranLo; i <= uranHi; i++)
  62.     kObjA[i] = kRainbowA[7];
  63.   for (i = starLo; i <= starHi; i++)
  64.     kObjA[i] = rStarBright[i-oNorm] < 1.0 ? kRainbowA[2] : kMainA[4];
  65. }
  66.  
  67.  
  68. /* This is the dispatch procedure for the entire program. After all the   */
  69. /* command switches have been processed, this routine is called to        */
  70. /* actually call the various routines to generate and display the charts. */
  71.  
  72. void Action()
  73. {
  74.   char sz[cchSzDef];
  75.   int i;
  76.  
  77. #ifdef WIN
  78.   is.fMult = fFalse;    /* Cleared here because no InitVariables routine. */
  79. #endif
  80.   is.fSzPersist = fFalse;
  81.   is.cchRow = 0;
  82.   AnsiColor(kDefault);
  83.   InitColors();
  84.   if (fSouthNode) {
  85.     szObjName[oSou] = "S.Node";
  86. #ifdef INTERPRET
  87.     szMindPart[oSou] =
  88.       "karmic past, and area of experience but little growth";
  89. #endif
  90.     ruler1[oSou] = sLeo;
  91.   }
  92.   szAspectAbbrev[aCon] = us.fParallel ? "Par" : "Con";
  93.   szAspectAbbrev[aOpp] = us.fParallel ? "CPr" : "Opp";
  94.  
  95.   /* First let's adjust the restriction status of the cusps, uranians, and */
  96.   /* fixed stars based on whether -C, -u, and -U switches are in effect.   */
  97.  
  98.   if (!us.fCusp)
  99.     for (i = cuspLo; i <= cuspHi; i++)
  100.       ignore[i] = ignore2[i] = fTrue;
  101.   if (!us.fUranian)
  102.     for (i = uranLo; i <= uranHi; i++)
  103.       ignore[i] = ignore2[i] = fTrue;
  104.   if (!us.nStar)
  105.     for (i = starLo; i <= starHi; i++)
  106.       ignore[i] = ignore2[i] = fTrue;
  107.  
  108.   /* If the -os switch is in effect, open a file and set a global to */
  109.   /* internally 'redirect' all screen output to.                     */
  110.  
  111.   if (is.szFileScreen) {
  112.     S = fopen(is.szFileScreen, "w");
  113.     if (S == NULL) {
  114.       sprintf(sz, "File %s can not be created.", is.szFileScreen);
  115.       PrintError(sz);
  116.       S = stdout;
  117.     }
  118.   } else
  119.     S = stdout;
  120.  
  121.   if (FPrintTables())    /* Print out any generic tables specified.        */
  122.     return;              /* If nothing else to do, we can exit right away. */
  123.   if (is.fMult) {
  124.     PrintL2();
  125.     is.fMult = fFalse;
  126.   }
  127.  
  128.   /* If -+ or -- switches in effect, then add the specified delta value to */
  129.   /* the date and use that as a new date before proceeding to make chart.  */
  130.  
  131.   if (us.dayDelta != 0) {
  132.     is.JD = (real)MdyToJulian(MM, DD+us.dayDelta, YY);
  133.     JulianToMdy(is.JD, &MM, &DD, &YY);
  134.   }
  135.  
  136.   /* Here we either do a normal chart or some kind of relationship chart. */
  137.  
  138.   if (!us.nRel) {
  139. #ifndef WIN
  140.     /* If chart info not in memory yet, then prompt the user for it. */
  141.     if (!is.fHaveInfo && !FInputData(szTtyCore))
  142.       return;
  143.     CastChart(fTrue);
  144. #else
  145.     if (wi.fCast) {
  146.       wi.fCast = fFalse;
  147.       CastChart(fTrue);
  148.     }
  149. #endif
  150.     ciMain = ciCore;
  151.   } else
  152.     CastRelation(fTrue);
  153. #ifndef WIN
  154.   ciSave = ciMain;
  155. #endif
  156.  
  157. #ifdef GRAPH
  158.   if (us.fGraphics)         /* If any of the X window switches in effect, */
  159.     FActionX();             /* then go make a graphics chart...           */
  160.   else
  161. #endif
  162.     PrintChart(is.fProgress);    /* Otherwise print chart on text screen. */
  163.  
  164.   if (us.fWriteFile)        /* If -o switch in effect, then write */
  165.     FOutputData();          /* the chart information to a file.   */
  166.  
  167.   if (S != stdout)    /* If we were internally directing chart display to a */
  168.     fclose(S);        /* file as with the -os switch, close it here.        */
  169.  
  170.   if (grid) {
  171.     DeallocateFar(grid);
  172.     grid = NULL;
  173.   }
  174. }
  175.  
  176.  
  177. #ifndef WIN
  178. /* Reset a few variables to their default values they have upon startup of */
  179. /* the program. We don't reset all variables, just the most volatile ones. */
  180. /* This is called when in the -Q loop to reset things like which charts to */
  181. /* display, but leave setups such as object restrictions and orbs alone.   */
  182.  
  183. void InitVariables()
  184. {
  185.   us.fInterpret = us.fProgress = is.fHaveInfo = is.fMult = fFalse;
  186.   us.nRel = us.dayDelta = 0;
  187.   is.szFileScreen = NULL;
  188.   ClearB((lpbyte)&us.fListing,
  189.     (int)((lpbyte)&us.fLoop - (lpbyte)&us.fListing));
  190. }
  191. #endif
  192.  
  193.  
  194. /*
  195. ******************************************************************************
  196. ** Command Switch Procedures.
  197. ******************************************************************************
  198. */
  199.  
  200. /* Given a string representing a command line (e.g. a macro string), go    */
  201. /* parse it into its various switches and parameters, then go process them */
  202. /* and change program settings. Basically a wrapper for other functions.   */
  203.  
  204. bool FProcessCommandLine(szLine)
  205. char *szLine;
  206. {
  207.   char szCommandLine[cchSzMax], *rgsz[MAXSWITCHES];
  208.   int argc, cb, fT;
  209.  
  210.   if (szLine == NULL)
  211.     return fTrue;
  212.   if (Mon != -1)
  213.     ciCore = ciMain;
  214.   cb = CchSz(szLine)+1;
  215.   CopyRgb((byte *)szLine, (byte *)szCommandLine, cb);
  216.   argc = NParseCommandLine(szCommandLine, rgsz);
  217.   fT = FProcessSwitches(argc, rgsz);
  218.   ciMain = ciCore;
  219.   return fT;
  220. }
  221.  
  222.  
  223. /* Given string representing a command line, convert it to an "argv" format */
  224. /* of an array of strings, one for each switch or parameter, i.e. exactly   */
  225. /* like the format of the command line as given when the program starts.    */
  226.  
  227. int NParseCommandLine(szLine, argv)
  228. char *szLine;
  229. char **argv;
  230. {
  231.   int argc = 1, fSpace = fTrue, fQuote = fFalse;
  232.   char *pch = szLine;
  233.  
  234.   /* Split the entered line up into its individual switch strings. */
  235.   while (*pch >= ' ' || *pch == chTab) {
  236.     if (*pch == ' ' || *pch == chTab) {
  237.       if (fSpace)
  238.         /* Skip over the current run of spaces between strings. */
  239.         ;
  240.       else {
  241.         /* First space after a string, end parameter here. */
  242.         if (!fQuote) {
  243.           *pch = chNull;
  244.           fSpace = fTrue;
  245.         }
  246.       }
  247.     } else {
  248.       if (fSpace) {
  249.         /* First character after run of spaces, begin parameter here. */
  250.         if (argc >= MAXSWITCHES-1) {
  251.           PrintWarning("Too many items - rest of line ignored.");
  252.           break;
  253.         }
  254.         fQuote = (*pch == '"');
  255.         argv[argc++] = pch + fQuote;
  256.         fSpace = fFalse;
  257.       } else
  258.         /* Skip over the current string. */
  259.         if (fQuote && *pch == '"') {
  260.           *pch = chNull;
  261.           fSpace = fTrue;
  262.         }
  263.     }
  264.     pch++;
  265.   }
  266.   argv[0] = szAppNameCore;
  267.   argv[argc] = NULL;         /* Set last string in switch array to Null. */
  268.   return argc;
  269. }
  270.  
  271.  
  272. /* This routine is called by the main program to interactively prompt the  */
  273. /* user for command switches and parameters, entered in the same format as */
  274. /* they would be on a command line. This needs to be called with certain   */
  275. /* systems which don't allow passing of a command line to the program,     */
  276. /* or when -Q is in effect. The result of this routine is returned to the  */
  277. /* main program which then processes it as done with a real command line.  */
  278.  
  279. int NPromptSwitches(line, argv)
  280. char *line, *argv[MAXSWITCHES];
  281. {
  282.   FILE *data;
  283.   char sz[cchSzDef];
  284.  
  285.   data = S; S = stdout;
  286.   is.cchRow = 0;
  287.   AnsiColor(kWhite);
  288.   sprintf(sz, "** %s version %s ", szAppName, szVersionCore); PrintSz(sz);
  289.   sprintf(sz, "(See '%cHc' switch for copyrights and credits.) **\n",
  290.     chSwitch); PrintSz(sz);
  291.   AnsiColor(kDefault);
  292.   PrintSz("Enter all parameter options below. ");
  293.   sprintf(sz, "(Enter '%cH' for help. Enter '.' to exit.)\n", chSwitch);
  294.   PrintSz(sz);
  295.   S = data;
  296.   InputString("Input command line", line);
  297.   PrintL();
  298.   return NParseCommandLine(line, argv);
  299. }
  300.  
  301.  
  302. /* This subprocedure is like FProcessSwitches() below, except that we only */
  303. /* process one switch, which we know to be one of the obscure -Y types.    */
  304.  
  305. int NProcessSwitchesRare(argc, argv, pos, fOr, fAnd, fNot)
  306. int argc, pos;
  307. bool fOr, fAnd, fNot;
  308. char **argv;
  309. {
  310.   int darg = 0, i, j, k;
  311.   real r;
  312.   char ch1, ch2;
  313.   OE oe;
  314.   lpbyte lpb;
  315.   int FPTR *lpn;
  316.   lpreal lpr;
  317. #ifdef INTERPRET
  318.   char *sz;
  319. #endif
  320.  
  321.   ch1 = argv[0][pos+1]; ch2 = argv[0][pos+2];
  322.   switch (argv[0][pos]) {
  323.   case chNull:
  324.     SwitchF(us.fSwitchRare);
  325.     break;
  326.  
  327.   case 'n':
  328.     SwitchF(us.fTrueNode);
  329.     break;
  330.  
  331.   case 'd':
  332.     SwitchF(us.fEuroDate);
  333.     break;
  334.  
  335.   case 't':
  336.     SwitchF(us.fEuroTime);
  337.     break;
  338.  
  339.   case 'C':
  340.     SwitchF(us.fSmartCusp);
  341.     break;
  342.  
  343.   case '8':
  344.     SwitchF(us.fClip80);
  345.     break;
  346.  
  347.   case 'Q':
  348.     if (argc <= 1) {
  349.       ErrorArgc("YQ");
  350.       return tcError;
  351.     }
  352.     i = atoi(argv[1]);
  353.     if (i < 0) {
  354.       ErrorValN("YQ", i);
  355.       return tcError;
  356.     }
  357.     us.nScrollRow = i;
  358.     darg++;
  359.     break;
  360.  
  361.   case 'o':
  362.     SwitchF(us.fWriteOld);
  363.     break;
  364.  
  365.   case 'c':
  366.     SwitchF(us.fHouseAngle);
  367.     break;
  368.  
  369.   case 'z':
  370.     if (argc <= 1) {
  371.       ErrorArgc("Yz");
  372.       return tcError;
  373.     }
  374.     us.lTimeAddition = atol(argv[1]);
  375.     darg++;
  376.     break;
  377.  
  378. #ifdef ARABIC
  379.   case 'P':
  380.     if (argc <= 1) {
  381.       ErrorArgc("YP");
  382.       return tcError;
  383.     }
  384.     i = atoi(argv[1]);
  385.     if (!FBetween(i, -1, 1)) {
  386.       ErrorValN("YP", i);
  387.       return tcError;
  388.     }
  389.     us.nArabicNight = i;
  390.     darg++;
  391.     break;
  392. #endif
  393.  
  394.   case 'E':
  395.     if (argc <= 17) {
  396.       ErrorArgc("YE");
  397.       return tcError;
  398.     }
  399.     i = NParseSz(argv[1], pmObject);
  400.     if (!FHelio(i)) {
  401.       ErrorValN("YE", i);
  402.       return tcError;
  403.     }
  404.     oe.sma = atof(argv[2]);
  405.     oe.ec0 = atof(argv[3]);  oe.ec1 = atof(argv[4]);  oe.ec2 = atof(argv[5]);
  406.     oe.in0 = atof(argv[6]);  oe.in1 = atof(argv[7]);  oe.in2 = atof(argv[8]);
  407.     oe.ap0 = atof(argv[9]);  oe.ap1 = atof(argv[10]); oe.ap2 = atof(argv[11]);
  408.     oe.an0 = atof(argv[12]); oe.an1 = atof(argv[13]); oe.an2 = atof(argv[14]);
  409.     oe.ma0 = atof(argv[15]); oe.ma1 = atof(argv[16]); oe.ma2 = atof(argv[17]);
  410.     rgoe[IoeFromObj(i)] = oe;
  411.     darg += 17;
  412.     break;
  413.  
  414.   case 'R':
  415.     if (argc <= 2) {
  416.       ErrorArgc("YR");
  417.       return tcError;
  418.     }
  419.     i = NParseSz(argv[1], pmObject); j = NParseSz(argv[2], pmObject);
  420.     if (ch1 == '0') {
  421.       ignore[0]  = i != 0;
  422.       ignore2[0] = j != 0;
  423.       darg += 2;
  424.       break;
  425.     }
  426.     if (!FItem(i)) {
  427.       ErrorValN("YR", i);
  428.       return tcError;
  429.     }
  430.     if (!FItem(j) || j < i) {
  431.       ErrorValN("YR", j);
  432.       return tcError;
  433.     }
  434.     if (argc <= 3+j-i) {
  435.       ErrorArgc("YR");
  436.       return tcError;
  437.     }
  438.     lpb = ch1 == 'T' ? ignore2 : ignore;
  439.     for (k = i; k <= j; k++)
  440.       lpb[k] = atoi(argv[3+k-i]) != 0;
  441.     darg += 3+j-i;
  442.     break;
  443.  
  444.   case 'A':
  445.     if (argc <= 2) {
  446.       ErrorArgc("YA");
  447.       return tcError;
  448.     }
  449.     k = ch1 == 'm' || ch1 == 'd' ? pmObject : pmAspect;
  450.     i = NParseSz(argv[1], k); j = NParseSz(argv[2], k);
  451.     k = ch1 == 'm' || ch1 == 'd' ? cObj : cAspect;
  452.     if (!FBetween(i, 1, k)) {
  453.       ErrorValN("YA", i);
  454.       return tcError;
  455.     }
  456.     if (!FBetween(j, 1, k) || j < i) {
  457.       ErrorValN("YA", j);
  458.       return tcError;
  459.     }
  460.     if (argc <= 3+j-i) {
  461.       ErrorArgc("YA");
  462.       return tcError;
  463.     }
  464.     lpr = ch1 == 'o' ? rAspOrb : (ch1 == 'm' ? rObjOrb :
  465.       (ch1 == 'd' ? rObjAdd : rAspAngle));
  466.     for (k = i; k <= j; k++)
  467.       lpr[k] = atof(argv[3+k-i]);
  468.     darg += 3+j-i;
  469.     break;
  470.  
  471.   case 'j':
  472.     if (argc <= 2 + 2*(ch1 == '0')) {
  473.       ErrorArgc("Yj");
  474.       return tcError;
  475.     }
  476.     if (ch1 == '0') {
  477.       rObjInf[oNorm+1] = atof(argv[1]);
  478.       rObjInf[oNorm+2] = atof(argv[2]);
  479.       rHouseInf[cSign+1]  = atof(argv[3]);
  480.       rHouseInf[cSign+2]  = atof(argv[4]);
  481.       darg += 4;
  482.       break;
  483.     }
  484.     k = ch1 == 'C' ? pmSign : (ch1 == 'A' ? pmAspect : pmObject);
  485.     i = NParseSz(argv[1], k); j = NParseSz(argv[2], k);
  486.     k = ch1 == 'C' ? cSign : (ch1 == 'A' ? cAspect : cObj);
  487.     if (!FBetween(i, 1, k)) {
  488.       ErrorValN("Yj", i);
  489.       return tcError;
  490.     }
  491.     if (!FBetween(j, 1, k) || j < i) {
  492.       ErrorValN("Yj", j);
  493.       return tcError;
  494.     }
  495.     if (argc <= 3+j-i) {
  496.       ErrorArgc("Yj");
  497.       return tcError;
  498.     }
  499.     lpr = ch1 == 'C' ? rHouseInf : (ch1 == 'A' ? rAspInf :
  500.       (ch1 == 'T' ? rTransitInf : rObjInf));
  501.     for (k = i; k <= j; k++)
  502.       lpr[k] = atof(argv[3+k-i]);
  503.     darg += 3+j-i;
  504.     break;
  505.  
  506. #ifdef INTERPRET
  507.   case 'I':
  508.     if (argc <= 2) {
  509.       ErrorArgc("YI");
  510.       return tcError;
  511.     }
  512.     i = NParseSz(argv[1],
  513.       ch1 == 'A' ? pmAspect : (ch1 == chNull ? pmObject : pmSign));
  514.     j = ch1 == 'A' ? cAspect : (ch1 == chNull ? oNorm : cSign);
  515.     if (!FBetween(i, 1, j)) {
  516.       ErrorValN("YI", i);
  517.       return tcError;
  518.     }
  519.     if (ch1 == 'A' && ch2 == '0')
  520.       ch1 = '0';
  521.     sz = SzPersist(argv[2]);
  522.     switch (ch1) {
  523.     case 'A':    szInteract[i]  = sz; break;
  524.     case '0':    szTherefore[i] = sz; break;
  525.     case chNull: szMindPart[i]  = sz; break;
  526.     case 'C':    szLifeArea[i]  = sz; break;
  527.     case 'v':    szDesire[i]    = sz; break;
  528.     default:     szDesc[i]      = sz;
  529.     }
  530.     darg += 2;
  531.     break;
  532. #endif
  533.  
  534.   case 'k':
  535.     if (argc <= 2 + 2*(ch1 == 'C')) {
  536.       ErrorArgc("Yk");
  537.       return tcError;
  538.     }
  539.     if (ch1 == 'C') {
  540.       kElemA[eFir] = NParseSz(argv[1], pmColor) & 15;
  541.       kElemA[eEar] = NParseSz(argv[2], pmColor) & 15;
  542.       kElemA[eAir] = NParseSz(argv[3], pmColor) & 15;
  543.       kElemA[eWat] = NParseSz(argv[4], pmColor) & 15;
  544.       darg += 4;
  545.       break;
  546.     }
  547.     k = ch1 == 'A' ? pmAspect : 0;
  548.     i = NParseSz(argv[1], k); j = NParseSz(argv[2], k);
  549.     k = ch1 == 'A' ? cAspect : (ch1 == '0' ? 7 : 8);
  550.     if (!FBetween(i, ch1 != chNull, k)) {
  551.       ErrorValN("Yk", i);
  552.       return tcError;
  553.     }
  554.     if (!FBetween(j, ch1 != chNull, k) || j < i) {
  555.       ErrorValN("Yk", j);
  556.       return tcError;
  557.     }
  558.     if (argc <= 3+j-i) {
  559.       ErrorArgc("Yk");
  560.       return tcError;
  561.     }
  562.     lpn = ch1 == 'A' ? kAspA : (ch1 == '0' ? kRainbowA : kMainA);
  563.     for (k = i; k <= j; k++)
  564.       lpn[k] = NParseSz(argv[3+k-i], pmColor) & 15;
  565.     darg += 3+j-i;
  566.     break;
  567.  
  568.   case 'F':
  569.     if (argc <= 8) {
  570.       ErrorArgc("YF");
  571.       return tcError;
  572.     }
  573.     i = NParseSz(argv[1], pmObject);
  574.     if (!FItem(i)) {
  575.       ErrorValN("YF", i);
  576.       return tcError;
  577.     }
  578.     r = Mod((real)(atoi(argv[2]) +
  579.       (NParseSz(argv[3], pmSign)-1)*30) + atof(argv[4])/60.0);
  580.     if (!FCusp(i))
  581.       planet[i] = r;
  582.     else {
  583.       j = Mod12(i-(cuspLo-1)+6);
  584.       if (FBetween(i, cuspLo-1+4, cuspLo-1+9)) {
  585.         house[i-(cuspLo-1)] = r;
  586.         house[j] = Mod(r + rDegHalf);
  587.       } else {
  588.         planet[i] = r;
  589.         planet[cuspLo-1+j] = Mod(r + rDegHalf);
  590.       }
  591.     }
  592.     j = atoi(argv[5]);
  593.     r = (j < 0 ? -1.0 : 1.0)*((real)abs(j) + atof(argv[6])/60.0);
  594.     planetalt[i] = Mod((r + rDegQuad) * 2.0) / 2.0 - rDegQuad;
  595.     ret[i] = RFromD(atof(argv[7]));
  596.     if (i <= oNorm)
  597.       SphToRec(atof(argv[8]), planet[i], planetalt[i],
  598.         &spacex[i], &spacey[i], &spacez[i]);
  599.     MM = -1;
  600.     darg += 8;
  601.     break;
  602.  
  603. #ifdef GRAPH
  604.   case 'X':
  605.     return NProcessSwitchesRareX(argc, argv, pos+1);
  606. #endif
  607.  
  608.   default:
  609.     ErrorSwitch(argv[0]);
  610.     return tcError;
  611.   }
  612.   return darg;    /* Return the value to be added to argc. */
  613. }
  614.  
  615.  
  616. /* Process a command switch line passed to the program. Read each entry in */
  617. /* the argument list and set all the program modes and charts to display.  */
  618.  
  619. bool FProcessSwitches(argc, argv)
  620. int argc;
  621. char **argv;
  622. {
  623.   int ich, i, j;
  624.   bool fNot, fOr, fAnd;
  625.   real rT;
  626.   char ch1, ch2, *pch;
  627.  
  628.   argc--; argv++;
  629.   while (argc) {
  630.     ch1 = argv[0][0];
  631.     fNot = fOr = fAnd = fFalse;
  632.     switch (ch1) {
  633.     case '=': fOr  = fTrue; break;
  634.     case '_': fAnd = fTrue; break;
  635.     case ':':               break;
  636.     default:  fNot = fTrue; break;
  637.     }
  638.     ich = 1 + FChSwitch(argv[0][0]);    /* Leading dash? */
  639.     ch1 = argv[0][ich];
  640.     ch2 = ch1 == chNull ? chNull : argv[0][ich+1];
  641.     switch (argv[0][ich-1]) {
  642.  
  643.     case 'H':
  644.       if (ch1 == 'c')
  645.         SwitchF(us.fCredit);
  646.       else if (ch1 == 'Y')
  647.         SwitchF(us.fSwitchRare);
  648. #ifdef ISG
  649.       else if (ch1 == 'X')
  650.         SwitchF(us.fKeyGraph);
  651. #endif
  652.       else if (ch1 == 'C')
  653.         SwitchF(us.fSign);
  654.       else if (ch1 == 'O')
  655.         SwitchF(us.fObject);
  656.       else if (ch1 == 'A')
  657.         SwitchF(us.fAspect);
  658.       else if (ch1 == 'F')
  659.         SwitchF(us.fConstel);
  660.       else if (ch1 == 'S')
  661.         SwitchF(us.fOrbitData);
  662.       else if (ch1 == 'I')
  663.         SwitchF(us.fMeaning);
  664.       else if (ch1 == 'e') {
  665.         SwitchF(us.fCredit); SwitchF(us.fSwitch); SwitchF(us.fSwitchRare);
  666.         SwitchF(us.fKeyGraph); SwitchF(us.fSign); SwitchF(us.fObject);
  667.         SwitchF(us.fAspect); SwitchF(us.fConstel); SwitchF(us.fOrbitData);
  668.         SwitchF(us.fMeaning);
  669.       } else
  670.         SwitchF(us.fSwitch);
  671.       break;
  672.  
  673.     case 'Q':
  674.       if (ch1 == '0')
  675.         SwitchF(us.fLoopInit);
  676.       SwitchF(us.fLoop);
  677.       break;
  678.  
  679.     case 'M':
  680.       i = (ch1 == '0');
  681.       if (argc <= 1+i) {
  682.         ErrorArgc("M");
  683.         return fFalse;
  684.       }
  685.       j = atoi(argv[1]);
  686.       if (!FValidMacro(j)) {
  687.         ErrorValN("M", j);
  688.         return fFalse;
  689.       }
  690.       j--;
  691.       if (i)
  692.         szMacro[j] = SzPersist(argv[2]);
  693.       else
  694.         FProcessCommandLine(szMacro[j]);
  695.       argc -= 1+i; argv += 1+i;
  696.       break;
  697.  
  698.     case 'Y':
  699.       i = NProcessSwitchesRare(argc, argv, ich, fOr, fAnd, fNot);
  700.       if (i < 0)
  701.         return fFalse;
  702.       argc -= i; argv += i;
  703.       break;
  704.  
  705.     /* Switches which determine the type of chart to display: */
  706.  
  707.     case 'v':
  708.       if (ch1 == '0')
  709.         SwitchF(us.fVelocity);
  710.       SwitchF(us.fListing);
  711.       break;
  712.  
  713.     case 'w':
  714.       if (ch1 == '0')
  715.         SwitchF(us.fWheelReverse);
  716.       if (argc > 1 && (i = atoi(argv[1]))) {
  717.         argc--; argv++;
  718.         if (!FValidWheel(i)) {
  719.           ErrorValN("w", i);
  720.           return fFalse;
  721.         }
  722.         us.nWheelRows = i;
  723.       }
  724.       SwitchF(us.fWheel);
  725.       break;
  726.  
  727.     case 'g':
  728.       if (ch1 == '0' || ch2 == '0')
  729.         SwitchF(us.fGridConfig);
  730.       if (ch1 == 'a')
  731.         SwitchF(us.fAppSep);
  732.       else if (ch1 == 'p')
  733.         SwitchF(us.fParallel);
  734. #ifdef X11
  735.       else if (ch1 == 'e') {
  736.         if (argc <= 1) {
  737.           ErrorArgc("geometry");
  738.           return fFalse;
  739.         }
  740.         gs.xWin = atoi(argv[1]);
  741.         if (argc > 2 && (gs.yWin = atoi(argv[2]))) {
  742.           argc--; argv++;
  743.         } else
  744.           gs.yWin = gs.xWin;
  745.         if (!FValidGraphx(gs.xWin)) {
  746.           ErrorValN("geometry", gs.xWin);
  747.           return fFalse;
  748.         }
  749.         if (!FValidGraphy(gs.yWin)) {
  750.           ErrorValN("geometry", gs.yWin);
  751.           return fFalse;
  752.         }
  753.         argc--; argv++;
  754.         break;
  755.       }
  756. #endif
  757.       SwitchF(us.fGrid);
  758.       break;
  759.  
  760.     case 'a':
  761.       SwitchF(us.fAspList);
  762.       if (ch1 == '0') {
  763.         SwitchF(us.fAspSummary);
  764.         ch1 = ch2;
  765.       }
  766.       if (ch1 == 'a')
  767.         SwitchF(us.fAppSep);
  768.       else if (ch1 == 'p')
  769.         SwitchF(us.fParallel);
  770.       break;
  771.  
  772.     case 'm':
  773.       if (ch1 == '0' || ch2 == '0')
  774.         SwitchF(us.fMidSummary);
  775.       if (ch1 == 'a')
  776.         SwitchF(us.fMidAspect);
  777.       SwitchF(us.fMidpoint);
  778.       break;
  779.  
  780.     case 'Z':
  781.       if (ch1 == '0')
  782.         SwitchF(us.fPrimeVert);
  783.       else if (ch1 == 'd')
  784.         SwitchF(us.fHorizonSearch);
  785.       SwitchF(us.fHorizon);
  786.       break;
  787.  
  788.     case 'S':
  789.       SwitchF(us.fOrbit);
  790.       break;
  791.  
  792.     case 'j':
  793.       if (ch1 == '0')
  794.         SwitchF(us.fInfluenceSign);
  795.       SwitchF(us.fInfluence);
  796.       break;
  797.  
  798.     case 'L':
  799.       if (ch1 == '0')
  800.         SwitchF(us.fLatitudeCross);
  801.       if (argc > 1 && (i = atoi(argv[1]))) {
  802.         argc--; argv++;
  803.         if (!FValidAstrograph(i)) {
  804.           ErrorValN("L", i);
  805.           return fFalse;
  806.         }
  807.         us.nAstroGraphStep = i;
  808.       }
  809.       SwitchF(us.fAstroGraph);
  810.       break;
  811.  
  812.     case 'K':
  813.       if (ch1 == 'y')
  814.         SwitchF(us.fCalendarYear);
  815.       SwitchF(us.fCalendar);
  816.       break;
  817.  
  818.     case 'd':
  819.       if (ch1 == 'p') {
  820.         us.fSolarArc = (ch2 == '0');
  821.         if (us.fSolarArc)
  822.           ch2 = argv[0][ich++ + 1];
  823.         i = (ch2 == 'y') + 2*(ch2 == 'Y');
  824. #ifdef TIME
  825.         j = i < 2 && (argv[0][ich+i+1] == 'n');
  826. #else
  827.         j = fFalse;
  828. #endif
  829.         if (!j && argc <= 2-(i&1)) {
  830.           ErrorArgc("dp");
  831.           return fFalse;
  832.         }
  833.         is.fProgress = us.fInDayMonth = fTrue;
  834.         Dst2 = us.dstDef; Zon2 = us.zonDef;
  835.         Lon2 = us.lonDef; Lat2 = us.latDef;
  836. #ifdef TIME
  837.         if (j)
  838.           GetTimeNow(&Mon2, &Day2, &Yea2, &Tim2, Zon2-Dst2);
  839. #endif
  840.         if (i) {
  841.           Mon2 = 0;
  842.           if (!j)
  843.             Yea2 = NParseSz(argv[1], pmYea);
  844.           us.nEphemYears = i == 2 ? atoi(argv[2]) : 1;
  845.         } else {
  846.           if (!j) {
  847.             Mon2 = NParseSz(argv[1], pmMon);
  848.             Yea2 = NParseSz(argv[2], pmYea);
  849.             if (!FValidMon(Mon2)) {
  850.               ErrorValN("dp", Mon2);
  851.               return fFalse;
  852.             }
  853.           }
  854.         }
  855.         if (!FValidYea(Yea2)) {
  856.           ErrorValN("dp", Yea2);
  857.           return fFalse;
  858.         }
  859.         if (!j) {
  860.           i = 2-(i&1);
  861.           argc -= i; argv += i;
  862.         }
  863.       } else if (ch1 == 'm' || ch1 == 'y' || ch1 == 'Y') {
  864.         if (ch1 == 'y')
  865.           us.nEphemYears = 1;
  866.         else if (ch1 == 'Y') {
  867.           if (argc <= 1) {
  868.             ErrorArgc("dY");
  869.             return fFalse;
  870.           }
  871.           i = atoi(argv[1]);
  872.           if (i < 1) {
  873.             ErrorValN("dY", i);
  874.             return fFalse;
  875.           }
  876.           us.nEphemYears = i;
  877.           argc--; argv++;
  878.         }
  879.         SwitchF(us.fInDayMonth);
  880.         Mon2 = (ch1 == 'm');
  881.       }
  882. #ifdef X11
  883.       else if (ch1 == 'i') {    /* -display switch for X */
  884.         if (argc <= 1) {
  885.           ErrorArgc("display");
  886.           return fFalse;
  887.         }
  888.         gs.szDisplay = SzPersist(argv[1]);
  889.         argc--; argv++;
  890.         break;
  891.       }
  892. #endif
  893.       else if (argc > 1 && (i = atoi(argv[1]))) {
  894.         if (!FValidDivision(i)) {
  895.           ErrorValN("d", i);
  896.           return fFalse;
  897.         }
  898.         us.nDivision = i;
  899.         argc--; argv++;
  900.       }
  901.       SwitchF(us.fInDay);
  902.       break;
  903.  
  904.     case 'D':
  905.       SwitchF(us.fInDayInf);
  906.       break;
  907.  
  908.     case 'E':
  909.       if (ch1 == 'Y' && argc <= 1) {
  910.         ErrorArgc("E");
  911.         return fFalse;
  912.       }
  913.       SwitchF(us.fEphemeris);
  914.       if (ch1 == 'y')
  915.         us.nEphemYears = us.fEphemeris ? 1 : 0;
  916.       else if (ch1 == 'Y') {
  917.         i = atoi(argv[1]);
  918.         if (i < 1) {
  919.           ErrorValN("EY", i);
  920.           return fFalse;
  921.         }
  922.         us.nEphemYears = i;
  923.       }
  924.       break;
  925.  
  926.     case 'e':
  927.       SwitchF(us.fListing); SwitchF(us.fWheel);
  928.       SwitchF(us.fGrid); SwitchF(us.fAspList); SwitchF(us.fMidpoint);
  929.       SwitchF(us.fHorizon); SwitchF(us.fOrbit);
  930.       SwitchF(us.fAstroGraph); SwitchF(us.fInfluence); SwitchF(us.fCalendar);
  931.       SwitchF(us.fInDay); SwitchF(us.fInDayInf);
  932.       SwitchF(us.fEphemeris);
  933.       SwitchF(us.fGridConfig); SwitchF(us.fInfluenceSign);
  934.       SwitchF(us.fLatitudeCross);
  935.       break;
  936.  
  937.     case 't':
  938.       SwitchF(us.fTransit);
  939.       Zon2 = us.zonDef; Dst2 = us.dstDef; Lon2 = us.lonDef; Lat2 = us.latDef;
  940.       if (ch1 == 'p') {
  941.         us.fSolarArc = (ch2 == '0');
  942.         if (us.fSolarArc)
  943.           ich++;
  944.         is.fProgress = fTrue;
  945.         ch1 = argv[0][++ich];
  946.       }
  947.       if (i = (ch1 == 'y') + 2*(ch1 == 'Y'))
  948.         ch1 = argv[0][++ich];
  949. #ifdef TIME
  950.       if (ch1 == 'n') {
  951.         GetTimeNow(&Mon2, &Day2, &Yea2, &Tim2, Zon2-Dst2);
  952.         if (i == 1)
  953.           Mon2 = 0;
  954.         else if (i > 1) {
  955.           Mon2 = -1; Day2 = NParseSz(argv[1], pmDay);
  956.         }
  957.         break;
  958.       }
  959. #endif
  960.       if (argc <= 2 - (i & 1)) {
  961.         ErrorArgc("t");
  962.         return fFalse;
  963.       }
  964.       if (i) {
  965.         if (i == 1)
  966.           Mon2 = 0;
  967.         else {
  968.           Mon2 = -1; Day2 = NParseSz(argv[2], pmDay);
  969.         }
  970.       } else {
  971.         Mon2 = NParseSz(argv[1], pmMon);
  972.         if (!FValidMon(Mon2)) {
  973.           ErrorValN("t", Mon2);
  974.           return fFalse;
  975.         }
  976.       }
  977.       Yea2 = NParseSz(argv[2 - (i > 0)], pmYea);
  978.       argc -= 2 - (i & 1); argv += 2 - (i & 1);
  979.       break;
  980.  
  981.     case 'T':
  982.       SwitchF(us.fTransitInf);
  983.       Zon2 = us.zonDef; Dst2 = us.dstDef; Lon2 = us.lonDef; Lat2 = us.latDef;
  984.       if (ch1 == 'p') {
  985.         is.fProgress = fTrue;
  986.         ch1 = argv[0][++ich];
  987.       }
  988. #ifdef TIME
  989.       if (ch1 == 'n') {
  990.         GetTimeNow(&Mon2, &Day2, &Yea2, &Tim2, Zon2-Dst2);
  991.         break;
  992.       }
  993. #endif
  994.       if (argc <= 3) {
  995.         ErrorArgc("T");
  996.         return fFalse;
  997.       }
  998.       Mon2 = NParseSz(argv[1], pmMon);
  999.       Day2 = NParseSz(argv[2], pmDay);
  1000.       Yea2 = NParseSz(argv[3], pmYea);
  1001.       if (!FValidMon(Mon2)) {
  1002.         ErrorValN("T", Mon2);
  1003.         return fFalse;
  1004.       } else if (!FValidDay(Day2, Mon2, Yea2)) {
  1005.         ErrorValN("T", Day2);
  1006.         return fFalse;
  1007.       } else if (!FValidYea(Yea2)) {
  1008.         ErrorValN("T", Yea2);
  1009.         return fFalse;
  1010.       }
  1011.       argc -= 3; argv += 3;
  1012.       break;
  1013.  
  1014. #ifdef ARABIC
  1015.     case 'P':
  1016.       if (argc > 1 && (i = atoi(argv[1]))) {
  1017.         argc--; argv++;
  1018.         if (!FValidPart(i)) {
  1019.           ErrorValN("P", i);
  1020.           return fFalse;
  1021.         }
  1022.         us.nArabicParts = i;
  1023.       }
  1024.       if (ch1 == 'z' || ch1 == 'n' || ch1 == 'f') {
  1025.         us.nArabic = ch1;
  1026.         ch1 = ch2;
  1027.       } else
  1028.         SwitchF(us.nArabic);
  1029.       if (ch1 == '0')
  1030.         SwitchF(us.fArabicFlip);
  1031.       break;
  1032. #endif
  1033.  
  1034. #ifdef INTERPRET
  1035.     case 'I':
  1036.       if (argc > 1 && (i = atoi(argv[1]))) {
  1037.         argc--; argv++;
  1038.         if (!FValidScreen(i)) {
  1039.           ErrorValN("I", i);
  1040.           return fFalse;
  1041.         }
  1042.         us.nScreenWidth = i;
  1043.       }
  1044.       SwitchF(us.fInterpret);
  1045.       break;
  1046. #endif
  1047.  
  1048.     /* Switches which affect how the chart parameters are obtained: */
  1049.  
  1050. #ifdef TIME
  1051.     case 'n':
  1052.       FInputData(szNowCore);
  1053.       if (ch1 == 'd')
  1054.         TT = 0.0;
  1055.       else if (ch1 == 'm') {
  1056.         DD = 1; TT = 0.0;
  1057.       } else if (ch1 == 'y') {
  1058.         MM = DD = 1; TT = 0.0;
  1059.       }
  1060.       break;
  1061. #endif
  1062.  
  1063.     case 'z':
  1064.       if (ch1 == '0') {
  1065.         if (argc <= 1 || RParseSz(argv[1], pmZon) == rLarge) {
  1066.           i = us.dstDef != 0.0;
  1067.           SwitchF(i);
  1068.           SS = us.dstDef = i ? 1.0 : 0.0;
  1069.         } else {
  1070.           SS = us.dstDef = RParseSz(argv[1], pmZon);
  1071.           if (!FValidDst(us.dstDef)) {
  1072.             ErrorValR("z0", us.dstDef);
  1073.             return fFalse;
  1074.           }
  1075.           argc--; argv++;
  1076.         }
  1077.         break;
  1078.       } else if (ch1 == 'l') {
  1079.         if (argc <= 2) {
  1080.           ErrorArgc("zl");
  1081.           return fFalse;
  1082.         }
  1083.         OO = us.lonDef = RParseSz(argv[1], pmLon);
  1084.         AA = us.latDef = RParseSz(argv[2], pmLat);
  1085.         if (!FValidLon(us.lonDef)) {
  1086.           ErrorValR("zl", us.lonDef);
  1087.           return fFalse;
  1088.         } else if (!FValidLat(us.latDef)) {
  1089.           ErrorValR("zl", us.latDef);
  1090.           return fFalse;
  1091.         }
  1092.         argc -= 2; argv += 2;
  1093.         break;
  1094.       } else if (ch1 == 't') {
  1095.         if (argc <= 1) {
  1096.           ErrorArgc("zt");
  1097.           return fFalse;
  1098.         }
  1099.         TT = RParseSz(argv[1], pmTim);
  1100.         if (!FValidTim(TT)) {
  1101.           ErrorValR("zt", TT);
  1102.           return fFalse;
  1103.         }
  1104.         argc--; argv++;
  1105.         break;
  1106.       } else if (ch1 == 'd') {
  1107.         if (argc <= 1) {
  1108.           ErrorArgc("zd");
  1109.           return fFalse;
  1110.         }
  1111.         DD = NParseSz(argv[1], pmDay);
  1112.         if (!FValidDay(DD, MM, YY)) {
  1113.           ErrorValN("zd", DD);
  1114.           return fFalse;
  1115.         }
  1116.         argc--; argv++;
  1117.         break;
  1118.       } else if (ch1 == 'i') {
  1119.         if (argc <= 2) {
  1120.           ErrorArgc("zi");
  1121.           return fFalse;
  1122.         }
  1123.         ciCore.nam = SzPersist(argv[1]);
  1124.         ciCore.loc = SzPersist(argv[2]);
  1125.         argc -= 2; argv += 2;
  1126.         break;
  1127.       }
  1128.       if (argc <= 1 || RParseSz(argv[1], pmZon) == rLarge)
  1129.         ZZ -= 1.0;
  1130.       else {
  1131.         ZZ = us.zonDef = RParseSz(argv[1], pmZon);
  1132.         if (!FValidZon(us.zonDef)) {
  1133.           ErrorValR("z", us.zonDef);
  1134.           return fFalse;
  1135.         }
  1136.         argc--; argv++;
  1137.       }
  1138.       break;
  1139.  
  1140.     case 'q':
  1141.       i = (ch1 == 'y' || ch1 == 'j') + 2*(ch1 == 'm') + 3*(ch1 == 'd') +
  1142.         4*(ch1 == chNull) + 7*(ch1 == 'a') + 8*(ch1 == 'b');
  1143.       if (argc <= i) {
  1144.         ErrorArgc("q");
  1145.         return fFalse;
  1146.       }
  1147.       is.fHaveInfo = fTrue;
  1148.       if (ch1 == 'j') {
  1149.         is.JD = atof(argv[1])+rRound;
  1150.         TT = RFract(is.JD);
  1151.         JulianToMdy(is.JD-TT, &MM, &DD, &YY);
  1152.         TT = DegToDec(TT * 24.0);
  1153.         SS = ZZ = 0.0; OO = us.lonDef; AA = us.latDef;
  1154.       } else {
  1155.         MM = i > 1 ? NParseSz(argv[1], pmMon) : 1;
  1156.         DD = i > 2 ? NParseSz(argv[2], pmDay) : 1;
  1157.         YY = NParseSz(argv[3-(i<3)-(i<2)], pmYea);
  1158.         TT = i > 3 ? RParseSz(argv[4], pmTim) : (i < 3 ? 0.0 : 12.0);
  1159.         SS = i > 7 ? RParseSz(argv[5], pmDst) : (i > 6 ? 0.0 : us.dstDef);
  1160.         ZZ = i > 6 ? RParseSz(argv[5 + (i > 7)], pmZon) : us.zonDef;
  1161.         OO = i > 6 ? RParseSz(argv[6 + (i > 7)], pmLon) : us.lonDef;
  1162.         AA = i > 6 ? RParseSz(argv[7 + (i > 7)], pmLat) : us.latDef;
  1163.         if (!FValidMon(MM)) {
  1164.           ErrorValN("q", MM);
  1165.           return fFalse;
  1166.         } else if (!FValidDay(DD, MM, YY)) {
  1167.           ErrorValN("q", DD);
  1168.           return fFalse;
  1169.         } else if (!FValidYea(YY)) {
  1170.           ErrorValN("q", YY);
  1171.           return fFalse;
  1172.         } else if (!FValidTim(TT)) {
  1173.           ErrorValR("q", TT);
  1174.           return fFalse;
  1175.         } else if (!FValidDst(SS)) {
  1176.           ErrorValR("q", SS);
  1177.           return fFalse;
  1178.         } else if (!FValidZon(ZZ)) {
  1179.           ErrorValR("a", ZZ);
  1180.           return fFalse;
  1181.         } else if (!FValidLon(OO)) {
  1182.           ErrorValR("a", OO);
  1183.           return fFalse;
  1184.         } else if (!FValidLat(AA)) {
  1185.           ErrorValR("a", AA);
  1186.           return fFalse;
  1187.         }
  1188.       }
  1189.       argc -= i; argv += i;
  1190.       break;
  1191.  
  1192.     case 'i':
  1193.       if (us.fNoRead) {
  1194.         ErrorArgv("i");
  1195.         return tcError;
  1196.       }
  1197.       if (argc <= 1) {
  1198.         ErrorArgc("i");
  1199.         return fFalse;
  1200.       }
  1201.       if (!FInputData(argv[1]))
  1202.         return fFalse;
  1203.       argc--; argv++;
  1204.       break;
  1205.  
  1206.     case '>':
  1207.       ch1 = 's';
  1208.       /* Fall through */
  1209.  
  1210.     case 'o':
  1211.       if (us.fNoWrite) {
  1212.         ErrorArgv("o");
  1213.         return tcError;
  1214.       }
  1215.       if (argc <= 1) {
  1216.         ErrorArgc("o");
  1217.         return fFalse;
  1218.       }
  1219.       if (ch1 == 's') {
  1220.         is.szFileScreen = SzPersist(argv[1]);
  1221.         argc--; argv++;
  1222.         break;
  1223.       } else if (ch1 == '0')
  1224.         SwitchF(us.fWritePos);
  1225.       SwitchF(us.fWriteFile);
  1226.       is.szFileOut = SzPersist(argv[1]);
  1227.       if (is.fSzPersist) {
  1228.         is.rgszComment = argv;
  1229.         do {
  1230.           argc--; argv++;
  1231.           is.cszComment++;
  1232.         } while (argc > 1 && !FChSwitch(argv[1][0]));
  1233.       }
  1234.       break;
  1235.  
  1236.     /* Switches which affect what information is used in a chart: */
  1237.  
  1238.     case 'R':
  1239.       if (ch1 == 'A') {
  1240.         while (argc > 1 && (i = NParseSz(argv[1], pmAspect)))
  1241.           if (!FAspect(i)) {
  1242.             ErrorValN("RA", i);
  1243.             return fFalse;
  1244.           } else {
  1245.             rAspOrb[i] = -rDegHalf;
  1246.             argc--; argv++;
  1247.           }
  1248.         break;
  1249.       }
  1250.       if (ch1 == 'T') {
  1251.         pch = (char *)ignore2;
  1252.         ch1 = argv[0][++ich];
  1253.       } else
  1254.         pch = (char *)ignore;
  1255.       if (ch1 == '0')
  1256.         for (i = 1; i <= cObj; i++)
  1257.           pch[i] = fTrue;
  1258.       else if (ch1 == '1') {
  1259.         for (i = 1; i <= cObj; i++)
  1260.           pch[i] = fFalse;
  1261.         us.fCusp = us.fUranian = us.nStar = fTrue;
  1262.       } else if (ch1 == 'C')
  1263.         for (i = cuspLo; i <= cuspHi; i++)
  1264.           SwitchF(pch[i]);
  1265.       else if (ch1 == 'u')
  1266.         for (i = uranLo; i <= uranHi; i++)
  1267.           SwitchF(pch[i]);
  1268.       else if (ch1 == 'U')
  1269.         for (i = starLo; i <= starHi; i++)
  1270.           SwitchF(pch[i]);
  1271.       else if (argc <= 1 || (!NParseSz(argv[1], pmObject))) {
  1272.         for (i = oChi; i <= oVes; i++)
  1273.           SwitchF(pch[i]);
  1274.         for (i = oLil; i <= oEP; i++)
  1275.           SwitchF(pch[i]);
  1276.       }
  1277.       while (argc > 1 && (i = NParseSz(argv[1], pmObject)))
  1278.         if (!FItem(i)) {
  1279.           ErrorValN("R", i);
  1280.           return fFalse;
  1281.         } else {
  1282.           SwitchF(pch[i]);
  1283.           argc--; argv++;
  1284.         }
  1285.       break;
  1286.  
  1287.     case 'C':
  1288.       SwitchF(us.fCusp);
  1289.       break;
  1290.  
  1291.     case 'u':
  1292.       SwitchF(us.fUranian);
  1293.       break;
  1294.  
  1295.     case 'U':
  1296.       if (ch1 == 'z' || ch1 == 'l' || ch1 == 'n' || ch1 == 'b')
  1297.         us.nStar = ch1;
  1298.       else
  1299.         SwitchF(us.nStar);
  1300.       break;
  1301.  
  1302.     case 'A':
  1303.       if (ch1 != 'o' && ch1 != 'm' && ch1 != 'd' && ch1 != 'a') {
  1304.         if (argc <= 1) {
  1305.           ErrorArgc("A");
  1306.           return fFalse;
  1307.         }
  1308.         i = NParseSz(argv[1], pmAspect);
  1309.         if (!FValidAspect(i)) {
  1310.           ErrorValN("A", i);
  1311.           return fFalse;
  1312.         }
  1313.         us.nAsp = i;
  1314.         argc--; argv++;
  1315.       } else {
  1316.         if (argc <= 2) {
  1317.           ErrorArgc("A");
  1318.           return fFalse;
  1319.         }
  1320.         i = NParseSz(argv[1], ch1 == 'o' || ch1 == 'a' ? pmAspect : pmObject);
  1321.         if (i < 1 || i > (ch1 == 'o' || ch1 == 'a' ? cAspect : oNorm)) {
  1322.           ErrorValN("A", i);
  1323.           return fFalse;
  1324.         }
  1325.         rT = RParseSz(argv[2], 0);
  1326.         if (rT < -rDegMax || rT > rDegMax) {
  1327.           ErrorValR("A", rT);
  1328.           return fFalse;
  1329.         }
  1330.         if (ch1 == 'o')
  1331.           rAspOrb[i] = rT;
  1332.         else if (ch1 == 'm')
  1333.           rObjOrb[i] = rT;
  1334.         else if (ch1 == 'd')
  1335.           rObjAdd[i] = rT;
  1336.         else
  1337.           rAspAngle[i] = rT;
  1338.         argc -= 2; argv += 2;
  1339.       }
  1340.       break;
  1341.  
  1342.     /* Switches which affect how a chart is computed: */
  1343.  
  1344.     case 'b':
  1345.       if (ch1 == '0')
  1346.         SwitchF(us.fSeconds);
  1347.       else if (ch1 == 'a')
  1348.         SwitchF(us.fPlacalcAst);
  1349. #ifdef PLACALC
  1350.       SwitchF(us.fPlacalc);
  1351. #endif
  1352.       is.fSeconds = us.fSeconds;
  1353.       break;
  1354.  
  1355.     case 'c':
  1356.       if (argc <= 1) {
  1357.         ErrorArgc("c");
  1358.         return fFalse;
  1359.       }
  1360.       i = NParseSz(argv[1], pmSystem);
  1361.       if (!FValidSystem(i)) {
  1362.         ErrorValN("c", i);
  1363.         return fFalse;
  1364.       }
  1365.       us.nHouseSystem = i;
  1366.       argc--; argv++;
  1367.       break;
  1368.  
  1369.     case 's':
  1370.       if (argc > 1 && ((rT = atof(argv[1])) != 0.0 || FNumCh(argv[1][0]))) {
  1371.         if (!FValidOffset(rT)) {
  1372.           ErrorValR("s", rT);
  1373.           return fFalse;
  1374.         }
  1375.         argc--; argv++;
  1376.         us.rZodiacOffset = rT;
  1377.       }
  1378.       if (ch1 == 'r')
  1379.         SwitchF(us.fEquator);
  1380.       else if (ch1 == 'h')
  1381.         us.nDegForm = 1;
  1382.       else if (ch1 == 'd')
  1383.         us.nDegForm = 2;
  1384.       else if (ch1 == 'z')
  1385.         us.nDegForm = 0;
  1386.       else
  1387.         SwitchF(us.fSidereal);
  1388.       break;
  1389.  
  1390.     case 'h':
  1391.       if (argc > 1 && (i = NParseSz(argv[1], pmObject))) {
  1392.         argc--; argv++;
  1393.       } else
  1394.         i = 1;
  1395.       if (!FValidCenter(i)) {
  1396.         ErrorValN("h", i);
  1397.         return fFalse;
  1398.       }
  1399.       us.objCenter = i;
  1400.       pch = szObjName[0];
  1401.       szObjName[0] = szObjName[us.objCenter];
  1402.       szObjName[us.objCenter] = pch;
  1403.       if (us.objCenter < oMoo)
  1404.         us.objCenter = 1-us.objCenter;
  1405.       break;
  1406.  
  1407.     case 'p':
  1408.       if (fAnd) {
  1409.         us.fProgress = fFalse;
  1410.         break;
  1411.       }
  1412.       us.fSolarArc = (ch1 == '0');
  1413.       if (us.fSolarArc)
  1414.         ch1 = (argv[0][++ich]);
  1415.       us.fProgress = fTrue;
  1416. #ifdef TIME
  1417.       if (ch1 == 'n') {
  1418.         GetTimeNow(&Mon, &Day, &Yea, &Tim, us.zonDef - us.dstDef);
  1419.         is.JDp = MdytszToJulian(Mon, Day, Yea, Tim, us.dstDef, us.zonDef);
  1420.         break;
  1421.       }
  1422. #endif
  1423.       if (ch1 == 'd') {
  1424.         if (argc <= 1) {
  1425.           ErrorArgc("pd");
  1426.           return fFalse;
  1427.         }
  1428.         us.rProgDay = atof(argv[1]);
  1429.         if (us.rProgDay == 0.0) {
  1430.           ErrorValR("pd", us.rProgDay);
  1431.           return fFalse;
  1432.         }
  1433.         argc--; argv++;
  1434.         break;
  1435.       }
  1436.       if (argc <= 3) {
  1437.         ErrorArgc("p");
  1438.         return fFalse;
  1439.       }
  1440.       Mon = NParseSz(argv[1], pmMon);
  1441.       Day = NParseSz(argv[2], pmDay);
  1442.       Yea = NParseSz(argv[3], pmYea);
  1443.       if (!FValidMon(Mon)) {
  1444.         ErrorValN("p", Mon);
  1445.         return fFalse;
  1446.       } else if (!FValidDay(Day, Mon, Yea)) {
  1447.         ErrorValN("p", Day);
  1448.         return fFalse;
  1449.       } else if (!FValidYea(Yea)) {
  1450.         ErrorValN("p", Yea);
  1451.         return fFalse;
  1452.       }
  1453.       is.JDp = MdytszToJulian(Mon, Day, Yea, 0.0, us.dstDef, us.zonDef);
  1454.       argc -= 3; argv += 3;
  1455.       break;
  1456.  
  1457.     case 'x':
  1458.       if (argc <= 1) {
  1459.         ErrorArgc("x");
  1460.         return fFalse;
  1461.       }
  1462.       i = atoi(argv[1]);
  1463.       if (!FValidHarmonic(i)) {
  1464.         ErrorValN("x", i);
  1465.         return fFalse;
  1466.       }
  1467.       us.nHarmonic = i;
  1468.       argc--; argv++;
  1469.       break;
  1470.  
  1471.     case '1':
  1472.       if (argc > 1 && (i = NParseSz(argv[1], pmObject))) {
  1473.         argc--; argv++;
  1474.       } else
  1475.         i = oSun;
  1476.       if (!FItem(i)) {
  1477.         ErrorValN("1", i);
  1478.         return fFalse;
  1479.       }
  1480.       us.objOnAsc = fAnd ? 0 : i;
  1481.       break;
  1482.  
  1483.     case '2':
  1484.       if (argc > 1 && (i = NParseSz(argv[1], pmObject))) {
  1485.         argc--; argv++;
  1486.       } else
  1487.         i = oSun;
  1488.       if (!FItem(i)) {
  1489.         ErrorValN("2", i);
  1490.         return fFalse;
  1491.       }
  1492.       us.objOnAsc = fAnd ? 0 : -i;
  1493.       break;
  1494.  
  1495.     case '3':
  1496.       SwitchF(us.fDecan);
  1497.       break;
  1498.  
  1499.     case 'f':
  1500.       SwitchF(us.fFlip);
  1501.       break;
  1502.  
  1503.     case 'G':
  1504.       SwitchF(us.fGeodetic);
  1505.       break;
  1506.  
  1507.     case 'F':
  1508.       if (argc <= 3) {
  1509.         ErrorArgc("F");
  1510.         return fFalse;
  1511.       }
  1512.       i = NParseSz(argv[1], pmObject);
  1513.       if (!FItem(i)) {
  1514.         ErrorValN("F", i);
  1515.         return fFalse;
  1516.       }
  1517.       force[i] = (NParseSz(argv[2], pmSign)-1.0)*30.0+DecToDeg(atof(argv[3]));
  1518.       if (force[i] < 0.0 || force[i] >= rDegMax) {
  1519.         ErrorValR("F", force[i]);
  1520.         return fFalse;
  1521.       } else
  1522.         force[i] += rDegMax;
  1523.       argc -= 3; argv += 3;
  1524.       break;
  1525.  
  1526.     case '+':
  1527.       if (argc > 1 && (i = atoi(argv[1])) != 0) {
  1528.         argc--; argv++;
  1529.       } else
  1530.         i = 1;
  1531.       us.dayDelta += i * (ch1 == 'y' ? 365 : (ch1 == 'm' ? 30 : 1));
  1532.       break;
  1533.  
  1534.     case chNull:
  1535.       if (ich <= 1)
  1536.         break;
  1537.       /* Fall thorugh */
  1538.  
  1539.     case '-':
  1540.       if (argc > 1 && (i = atoi(argv[1])) != 0) {
  1541.         argc--; argv++;
  1542.       } else
  1543.         i = 1;
  1544.       us.dayDelta -= i * (ch1 == 'y' ? 365 : (ch1 == 'm' ? 30 : 1));
  1545.       break;
  1546.  
  1547.     /* Switches for relationship and comparison charts: */
  1548.  
  1549.     case 'r':
  1550.       if (fAnd) {
  1551.         us.nRel = 0;
  1552.         break;
  1553.       }
  1554.       i = 2 + 2*((ch1 == 'c' || ch1 == 'm') && ch2 == '0');
  1555.       if (argc <= i) {
  1556.         ErrorArgc("r");
  1557.         return fFalse;
  1558.       }
  1559.       if (ch1 == 'c')
  1560.         us.nRel = rcComposite;
  1561.       else if (ch1 == 'm')
  1562.         us.nRel = rcMidpoint;
  1563.       else if (ch1 == 'd')
  1564.         us.nRel = rcDifference;
  1565. #ifdef BIORHYTHM
  1566.       else if (ch1 == 'b')
  1567.         us.nRel = rcBiorhythm;
  1568. #endif
  1569.       else if (ch1 == '0')
  1570.         us.nRel = rcDual;
  1571.       else if (ch1 == 't')
  1572.         us.nRel = rcTransit;
  1573.       else if (ch1 == 'p') {
  1574.         us.nRel = rcProgress;
  1575.         us.fSolarArc = (ch2 == '0');
  1576.       } else
  1577.         us.nRel = rcSynastry;
  1578.       is.szFile = SzPersist(argv[1]); is.szFile2 = SzPersist(argv[2]);
  1579.       if (is.fSzInteract) {
  1580.         if (!FInputData(is.szFile2))
  1581.           return fFalse;
  1582.         ciTwin = ciCore;
  1583.         if (!FInputData(is.szFile))
  1584.           return fFalse;
  1585.       }
  1586.       if (i > 2) {
  1587.         us.nRatio1 = atoi(argv[3]);
  1588.         us.nRatio2 = atoi(argv[4]);
  1589.         if (us.nRatio1 == us.nRatio2)
  1590.           us.nRatio1 = us.nRatio2 = 1;
  1591.       }
  1592.       argc -= i; argv += i;
  1593.       break;
  1594.  
  1595. #ifdef TIME
  1596.     case 'y':
  1597.       if (argc <= 1) {
  1598.         ErrorArgc("y");
  1599.         return fFalse;
  1600.       }
  1601.       if (ch1 == 'd')
  1602.         us.nRel = rcDifference;
  1603. #ifdef BIORHYTHM
  1604.       else if (ch1 == 'b')
  1605.         us.nRel = rcBiorhythm;
  1606. #endif
  1607.       else if (ch1 == 't')
  1608.         us.nRel = rcTransit;
  1609.       else if (ch1 == 'p') {
  1610.         us.nRel = rcProgress;
  1611.         us.fSolarArc = (ch2 == '0');
  1612.       } else
  1613.         us.nRel = rcDual;
  1614.       is.szFile = SzPersist(argv[1]); is.szFile2 = szNowCore;
  1615.       argc--; argv++;
  1616.       break;
  1617. #endif
  1618.  
  1619.     /* Switches to access graphics options: */
  1620.  
  1621.     case 'k':
  1622.       if (ch1 == '0')
  1623.         us.fAnsi = 2;
  1624.       else
  1625.         SwitchF(us.fAnsi);
  1626.       break;
  1627.  
  1628. #ifdef PCG
  1629.     case 'V':
  1630.       if (argc <= 1) {
  1631.         ErrorArgc("V");
  1632.         return fFalse;
  1633.       }
  1634.       i = atoi(argv[1]);
  1635.       if (!FValidTextrows(i)) {
  1636.         ErrorValN("V", i);
  1637.         return fFalse;
  1638.       }
  1639.       gs.nTextRows = i;
  1640.       argc--; argv++;
  1641.       break;
  1642. #endif
  1643.  
  1644. #ifdef GRAPH
  1645.     case 'X':
  1646.       if (us.fNoGraphics) {
  1647.         ErrorArgv("X");
  1648.         return fFalse;
  1649.       }
  1650.       i = NProcessSwitchesX(argc, argv, ich, fOr, fAnd, fNot);
  1651.       if (i < 0)
  1652.         return fFalse;
  1653.       SwitchF2(us.fGraphics);
  1654.       argc -= i; argv += i;
  1655.       break;
  1656.  
  1657. #ifdef WIN
  1658.     case 'W':
  1659.       i = NProcessSwitchesW(argc, argv, ich, fOr, fAnd, fNot);
  1660.       if (i < 0)
  1661.         return fFalse;
  1662.       argc -= i; argv += i;
  1663.       break;
  1664. #endif
  1665. #endif /* GRAPH */
  1666.  
  1667.     case '0':
  1668.       while (ch1 != chNull) {
  1669.         switch (ch1) {
  1670.         case 'o': us.fNoWrite    = fTrue; break;
  1671.         case 'i': us.fNoRead     = fTrue; break;
  1672.         case 'q': us.fNoQuit     = fTrue; break;
  1673.         case 'X': us.fNoGraphics = fTrue; break;
  1674.         }
  1675.         ch1 = (argv[0][++ich]);
  1676.       }
  1677.       break;
  1678.  
  1679.     case ';':    /* The -; switch means don't process the rest of the line. */
  1680.       return fTrue;
  1681.  
  1682.     case '@':    /* The -@ switch is just a system flag indicator no-op. */
  1683.       break;
  1684.  
  1685.     case '.':                /* "-." is usually used to exit the -Q loop. */
  1686.       Terminate(tcForce);
  1687.  
  1688.     case 'B':                /* For no useful reason, -B sounds a beep. */
  1689. #ifndef WIN
  1690.       putchar(chBell);
  1691. #else
  1692.       MessageBeep((UINT)-1);
  1693. #endif
  1694.       break;
  1695.  
  1696.     default:
  1697.       ErrorSwitch(argv[0]);
  1698.       return fFalse;
  1699.     }
  1700.     argc--; argv++;
  1701.   }
  1702.   return fTrue;
  1703. }
  1704.  
  1705.  
  1706. /*
  1707. ******************************************************************************
  1708. ** Main Program.
  1709. ******************************************************************************
  1710. */
  1711.  
  1712. #ifndef WIN
  1713. #ifndef NOMAIN
  1714. /* The main program, the starting point for Astrolog, follows. This routine */
  1715. /* basically consists of a loop, inside which we read a command line, and   */
  1716. /* go process it, before actually calling a routine to do the neat stuff.   */
  1717.  
  1718. #ifdef SWITCHES
  1719. void main(argc, argv)
  1720. int argc;
  1721. char **argv;
  1722. {
  1723. #else
  1724. void main()
  1725. {
  1726.   int argc;
  1727.   char **argv;
  1728. #endif
  1729.   char szCommandLine[cchSzMax], *rgsz[MAXSWITCHES];
  1730.  
  1731.   /* Read in info from the astrolog.dat file. */
  1732.   FProcessSwitchFile(DEFAULT_INFOFILE, NULL);
  1733.  
  1734. LBegin:
  1735. #ifdef PCG
  1736.   if (gs.nTextRows > 0) {
  1737.     PcSetTextRows(gs.nTextRows);
  1738.     neg(gs.nTextRows);
  1739.   }
  1740. #endif
  1741.   if (us.fNoSwitches) {                             /* Go prompt for    */
  1742.     argc = NPromptSwitches(szCommandLine, rgsz);    /* switches if we   */
  1743.     argv = rgsz;                                    /* don't have them. */
  1744.   }
  1745.   is.szProgName = argv[0];
  1746.   is.fSzPersist = fTrue;
  1747.   if (FProcessSwitches(argc, argv)) {
  1748.     if (!us.fNoSwitches && us.fLoopInit) {
  1749.       us.fNoSwitches = fTrue;
  1750.       goto LBegin;
  1751.     }
  1752. #ifdef PCG
  1753.     if (gs.nTextRows > 0) {
  1754.       PcSetTextRows(gs.nTextRows);
  1755.       neg(gs.nTextRows);
  1756.     }
  1757. #endif
  1758.     Action();
  1759.   }
  1760.   if (us.fLoop || us.fNoQuit) { /* If -Q in effect loop back and get switch */
  1761.     PrintL2();                  /* info for another chart to display.       */
  1762.     InitVariables();
  1763.     us.fLoop = us.fNoSwitches = fTrue;
  1764.     goto LBegin;
  1765.   }
  1766.   Terminate(tcOK);    /* The only standard place to exit Astrolog is here. */
  1767. }
  1768. #endif /* NOMAIN */
  1769. #endif /* WIN */
  1770.  
  1771. /* astrolog.c */
  1772.